package com.hjq.permissions;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.app.AbilityContext;
import ohos.app.Context;
import ohos.utils.IntentConstants;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * XXPermissions 开放类
 */
public final class XXPermissions {
    /**
     * 权限设置页跳转请求码
     */
    public static final int REQUEST_CODE = 1024;

    private static XXPermissions sInstance;

    /**
     * 调试模式
     */
    private static Boolean sDebugMode;

    /**
     * 权限列表
     */
    protected List<String> mPermissions;

    /**
     * ability  引用对象
     */
    private WeakReference<Ability> mWeakReference;

    private PermissionModule mPerMissionModule;

    private LifePermissionObserver mLifePermissionObserver;

    private OnPermission mCallback;

    /**
     * 是否去应用的权限详情
     */
    private boolean mIsJumpToPermissionDetail;

    /**
     * 私有化构造函数
     */
    private XXPermissions(Ability ability) {
        init(ability);
    }

    private void init(Ability ability) {
        mWeakReference = new WeakReference<>(ability);
        addLifeCycleObserver();
    }

    /**
     * with(链式调用)
     * @param context context
     * @return XXPermissions
     */
    public static XXPermissions with(Context context) {
        return with(PermissionUtils.getActivity(context));
    }

    /**
     * 设置请求的对象
     *
     * @param ability 当前 ability，也可以传入栈顶的 ability
     * @return XXPermissions
     */
    public static XXPermissions with(Ability ability) {
        if (ability == null) {
            throw new PermissionException("reqPermission context is null");
        }
        if (sInstance != null) {
            sInstance.onDestroy();
        }
        sInstance = new XXPermissions(ability);
        return sInstance;
    }

    /**
     * 添加生命周期的监听
     */
    private void addLifeCycleObserver() {
        if (mWeakReference == null) {
            return;
        }
        mLifePermissionObserver = new LifePermissionObserver(this);
        if (mWeakReference.get() != null) {
            mWeakReference.get().getLifecycle().addObserver(mLifePermissionObserver);
        }
    }

    /**
     * 移除生命周期的监听
     */
    protected void removeLiftCycleObserver() {
        if (mWeakReference == null || mLifePermissionObserver == null) {
            return;
        }
        if (mWeakReference.get() != null) {
            mWeakReference.get().getLifecycle().removeObserver(mLifePermissionObserver);
        }
    }

    /**
     * 销毁
     */
    protected void onDestroy() {
        removeLiftCycleObserver();
        if (mPermissions != null) {
            mPermissions.clear();
        }
        if (mWeakReference != null) {
            mWeakReference.clear();
            mWeakReference = null;
        }
        mIsJumpToPermissionDetail = false;
        sDebugMode = false;
        mCallback = null;
        mPerMissionModule = null;
        mLifePermissionObserver = null;
        sInstance = null;
    }

    /**
     * 设置是否为调试模式
     *
     * @param debug debug
     */
    public static void setDebugMode(boolean debug) {
        sDebugMode = debug;
    }

    /**
     * 设置权限组
     *
     * @param permissions permissions
     * @return XXPermissions
     */
    public XXPermissions permission(String... permissions) {
        if (mPermissions == null) {
            mPermissions = PermissionUtils.asArrayList(permissions);
        } else {
            mPermissions.addAll(PermissionUtils.asArrayList(permissions));
        }
        return this;
    }

    /**
     * 设置权限组
     *
     * @param permissions permissions
     * @return XXPermissions
     */
    public XXPermissions permission(String[]... permissions) {
        if (mPermissions == null) {
            int length = 0;
            for (String[] permission : permissions) {
                length += permission.length;
            }
            mPermissions = new ArrayList<>(length);
        }
        for (String[] group : permissions) {
            mPermissions.addAll(PermissionUtils.asArrayList(group));
        }
        return this;
    }

    /**
     * 设置权限组
     *
     * @param permissions permissions
     * @return XXPermissions
     */
    public XXPermissions permission(List<String> permissions) {
        if (mPermissions == null) {
            mPermissions = permissions;
        } else {
            mPermissions.addAll(permissions);
        }
        return this;
    }

    /**
     * 请求权限
     *
     * @param callback callback
     */
    public void request(OnPermission callback) {
        mIsJumpToPermissionDetail = false;
        if (mWeakReference == null) {
            return;
        }
        Ability ability = mWeakReference.get();
        // 如果传入 ability 为空或者 ability 状态非法则直接屏蔽这次权限申请
        if (ability == null || ability.isTerminating()) {
            return;
        }

        // 必须要传入权限或者权限组才能申请权限
        if (mPermissions == null || mPermissions.isEmpty()) {
            throw new IllegalArgumentException("The requested permission cannot be empty");
        }
        this.mCallback = callback;
        setDebugMode(PermissionUtils.isDebugMode(ability));
        PermissionUtils.checkPermissionManifest(ability, mPermissions);
        mPerMissionModule = new PermissionModule(callback);
        if (PermissionUtils.isAbilityActive(ability)) {
            // 申请没有授予过的权限
            beginReqPermission();
        }
    }

    /**
     * 开始请求权限
     */
    protected void beginReqPermission() {
        if (mPerMissionModule == null) {
            return;
        }
        if (mWeakReference == null) {
            return;
        }
        Ability ability = mWeakReference.get();
        if (ability == null || ability.isTerminating()) {
            return;
        }
        mPerMissionModule.beginRequest(ability, this, new ArrayList<>(mPermissions));
    }

    /**
     * 申请权限的回调
     *
     * @param ability      ability
     * @param requestCode  int
     * @param permissions  permissions
     * @param grantResults grantResults
     */
    public static void addPermissionsForResult(
            Ability ability, int requestCode, String[] permissions, int[] grantResults) {
        if (sInstance == null || ability == null || ability.isTerminating()) {
            return;
        }
        if (sInstance.mWeakReference == null) {
            return;
        }
        Ability reqAbility = sInstance.mWeakReference.get();
        if (reqAbility == null || reqAbility != ability) {
            return;
        }
        if (sInstance.mPerMissionModule == null) {
            return;
        }
        sInstance.mPerMissionModule.addPermissionsForResult(ability, requestCode, permissions, grantResults);
        if (!sInstance.mIsJumpToPermissionDetail) {
            sInstance.onDestroy();
        }
    }

    /**
     * 应用权限详情界面回调
     *
     * @param requestCode int
     */
    public static void onAbilityResult(int requestCode) {
        if (requestCode != REQUEST_CODE) {
            return;
        }
        if (sInstance == null || sInstance.mWeakReference == null) {
            return;
        }
        sInstance.mIsJumpToPermissionDetail = false;
        Ability reqAbility = sInstance.mWeakReference.get();
        if (reqAbility == null || reqAbility.isTerminating()) {
            return;
        }
        if (sInstance.mPerMissionModule == null) {
            sInstance.mPerMissionModule = new PermissionModule(sInstance.mCallback);
        }
        PermissionUtils.checkPermissionManifest(reqAbility, sInstance.mPermissions);
        sInstance.mPerMissionModule.onAbilityResult(reqAbility, sInstance.mPermissions);
        sInstance.onDestroy();
    }

    /**
     *
     * 判断一个或多个权限是否全部授予了
     *
     * @param context     context
     * @param permissions permissions
     * @return boolean
     */
    public static boolean hasPermission(Context context, String... permissions) {
        if (permissions == null || permissions.length == 0) {
            return hasPermission(context, PermissionUtils.getManifestPermissions(context));
        } else {
            return hasPermission(context, PermissionUtils.asArrayList(permissions));
        }
    }

    public static boolean hasPermission(Context context, List<String> permissions) {
        return PermissionUtils.isPermissionGranted(context, permissions);
    }

    /**
     * 判断一个或多个权限组是否全部授予了
     *
     * @param context     context
     * @param permissions permissions
     * @return Boolean
     */
    public static boolean hasPermission(Context context, String[]... permissions) {
        List<String> permissionList = new ArrayList<>();
        for (String[] group : permissions) {
            permissionList.addAll(PermissionUtils.asArrayList(group));
        }
        return PermissionUtils.isPermissionGranted(context, permissionList);
    }

    /**
     * 跳转到已安装应用的列表界面
     *
     * @param ability AbilityContext
     */
    public static void startPermissionActivity(AbilityContext ability) {
        Intent intent = new Intent();
        Intent.OperationBuilder builder = new Intent.OperationBuilder();
        builder.withAction(IntentConstants.ACTION_MANAGE_APPLICATIONS_SETTINGS);
        intent.setOperation(builder.build());
        intent.addFlags(Intent.FLAG_ABILITY_CONTINUATION);
        if (ability instanceof Ability) {
            ((Ability) ability).startAbilityForResult(intent, REQUEST_CODE);
        } else if (ability instanceof AbilitySlice) {
            ((AbilitySlice) ability).startAbilityForResult(intent, REQUEST_CODE);
        } else {
            throw new PermissionException("context exception");
        }
    }

    /**
     * 跳转到已安装应用的列表界面
     *
     * @param ability     AbilityContext
     * @param permissions permissions
     * @param callback    OnPermission
     */
    public static void startPermissionActivity(AbilityContext ability, String[] permissions, OnPermission callback) {
        with(ability);
        if (sInstance != null) {
            sInstance.permission(permissions);
            sInstance.mCallback = callback;
            sInstance.mIsJumpToPermissionDetail = true;
        }
        startPermissionActivity(ability);
    }
}
